from datetime import datetime, timedelta

from flask import Blueprint, request, jsonify, send_from_directory
from flask_cors import CORS
from sqlalchemy import func

from module import Report, User, Task
from extension import db
from views.auth import admin_required
from module import Assignment
from flask import jsonify, Blueprint
from flask_login import current_user
from extension import socketio
from flask_socketio import join_room, emit, leave_room
from flask_jwt_extended import jwt_required, get_jwt_identity
from api import BaiduDistance
from sqlalchemy import cast, Date

tb = Blueprint('task', __name__)


@tb.route('/get_user_statement', methods=['GET'])
@jwt_required()
@admin_required
def get_user_statement():
    users = User.query.all()
    user_statement = []
    for user in users:
        task = Task.query.filter_by(tid=user.assigned).first()
        if (not user.is_admin()):
            if task:
                user_statement.append({
                    'uid': user.uid,
                    'name': user.name,
                    'assigned': user.assigned,
                    'task_placex': task.placex,
                    'task_placey': task.placey,
                    'starttime': task.starttime,
                    'endtime': task.endtime
                })
            else:
                user_statement.append({
                    'uid': user.uid,
                    'name': user.name,
                    'assigned': user.assigned,
                    'task_placex': '',
                    'task_placey': '',
                    'starttime': '',
                    'endtime': ''
                })
    return jsonify(user_statement)


@tb.route('/get_task_statement', methods=['GET'])
@jwt_required()
@admin_required
def get_task_statement():
    now = datetime.now()  # 当前UTC时间
    four_hours_ago = now - timedelta(hours=4)
    task_statement = []
    today = datetime.now().date()
    print(today)
    tasks = Task.query.filter(Task.starttime >= four_hours_ago).all()
    for task in tasks:
        task_statement.append({
            'tid': task.tid,
            'placex': task.placex,
            'placey': task.placey,
            'finished': task.finished,
            'starttime': task.starttime,
            'endtime': task.endtime,
        })

    return jsonify(task_statement), 200


@tb.route('/modify_assign_statement', methods=['POST'])
@jwt_required()
@admin_required
def modify_task_statement():
    task_id = request.json['tid']
    user_ids = request.json['uids']

    task = Task.query.filter_by(tid=task_id).first()
    if task.finished:
        return jsonify({'message': 'Task already finished'}), 200

    data = {
        'users': [],
        'addressx': task.placex,
        'addressy': task.placey,
    }
    # 分配任务给多个用户
    for user_id in user_ids:
        # 检查用户是否存在
        user = User.query.filter_by(uid=user_id).first()
        if not user:
            continue  # 如果用户不存在，跳过此用户

        if user.assigned not in [0, task_id]:
            continue

        # 检查用户是否已被分配任务(是否是取消该调度的)
        if user.assigned != 0:
            assigned = Assignment.query.filter_by(tid=task_id, uid=user_id).first()
            if assigned:
                db.session.delete(assigned)
            user.assigned = 0
        else:
            # 创建新的任务分配
            assignment = Assignment(uid=user_id, tid=task_id, confirmed=False)
            db.session.add(assignment)
            data['users'].append(user.uid)
            # 更新用户的分配状态
            user.assigned = task_id
    emit_assignment(data)
    # 提交数据库更改
    db.session.commit()

    return jsonify({'message': 'Task assigned to multiple users'}), 200


@tb.route('/delete_assign_statement', methods=['POST'])
@jwt_required()
@admin_required
def delete_assign_statement():
    task_id = request.json['tid']
    try:
        # 批量更新 User 状态
        users_to_update = User.query.filter(User.uid.in_(
            db.session.query(Assignment.uid).filter_by(tid=task_id)
        )).all()
        for user in users_to_update:
            user.assigned = 0
        Assignment.query.filter_by(tid=task_id).delete()

        db.session.commit()
        return jsonify({'message': 'Assignment deleted'}), 200
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@tb.route('/finish_task', methods=['POST'])
@jwt_required()
@admin_required
def finish_task():
    try:
        task_id = request.json.get('tid')
        if not task_id:
            return jsonify({'error': 'Task ID is required'}), 400

        task = Task.query.get(task_id)
        if not task:
            return jsonify({'error': 'Task not found'}), 404

        assigns = Assignment.query.filter_by(tid=task_id).all()
        for assignment in assigns:
            user = User.query.filter_by(uid=assignment.uid).first()
            if not user:
                return jsonify({'error': 'User not found'}), 404
            user.assigned = 0
            db.session.commit()

        task.finished = True
        task.endtime = datetime.now()
        db.session.commit()

        return jsonify({'message': 'Task finished successfully'}), 200
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': str(e)}), 500


@tb.route('/get_my_tasks', methods=['POST'])
@jwt_required()
def get_my_tasks():
    uid = get_jwt_identity().get('uid')
    print(uid)
    assigns = Assignment.query.filter_by(uid=uid).all()

    taskInfo = []
    for assign in assigns:
        task = Task.query.filter_by(tid=assign.tid).first()
        taskInfo.append({
            'tid': task.tid,
            'placex': task.placex,
            'placey': task.placey,
            'finished': task.finished,
            'starttime': task.starttime,
            'endtime': task.endtime,
            'confirmed':assign.confirmed
        })
    return jsonify(taskInfo), 200


@tb.route('/confirm', methods=['POST'])
@jwt_required()
def confirm_task():
    uid = get_jwt_identity().get('uid')
    tid = request.json['tid']

    # 查找任务
    arrange = Assignment.query.filter_by(tid=tid, uid=uid).first()
    user = User.query.filter_by(uid=uid).first()
    if not arrange:
        return jsonify({'error': 'arrange not found'}), 404

    # 更新任务的 confirm 状态
    arrange.confirmed = 1

    # 更新用户的状态
    user.assigned = tid

    db.session.commit()

    return jsonify({'message': 'Task confirmed and user status updated'}), 200


@tb.route('/auto_generate_task', methods=['POST'])
@jwt_required()
@admin_required
def generate_task():
    print("Auto generate task triggered")


@socketio.on('connect')
def connect(uid):
    join_room(uid)
    return jsonify({'message': 'Connected'})


@socketio.on('disconnect')
def disconnect(uid):
    leave_room(uid)
    return jsonify({'message': 'Disconnected'})


def emit_assignment(data):
    for room in data['users']:
        emit('assign', "" + str(data["addressx"]) + "," + str(data["addressy"]), to=room, namespace='/')


@tb.route('/assign', methods=['POST'])
def assign():
    data = request.get_json()
    emit_assignment(data)
    return jsonify({'message': 'Assignment added'})


@tb.route('/auto_assign', methods=['POST'])
@jwt_required()
@admin_required
def auto_assign():
    today = datetime.now().date()
    task_id = Task.query.filter(Task.finished == False, cast(Task.starttime, Date) == today).all()
    users = User.query.filter_by(assigned=0, role=1).all()

    # 获取空闲警员的数量
    num_task = len(task_id)
    num_users = len(users)
    idx = 0
    # Assuming you have a distance array where each element corresponds to the distance of the task
    distances = [BaiduDistance.short_distance2([task.placey, task.placex]) for task in
                 task_id]  # Replace with actual distance fetching logic
    distances = [d for d in distances if d is not None]

    # Pair tasks with their distances and sort by distance
    tasks_with_distances = sorted(zip(task_id, distances), key=lambda x: x[1])
    print(tasks_with_distances)

    if (num_users >= num_task):
        for task in task_id:
            if idx < num_users:
                assignment = Assignment(uid=users[idx].uid, tid=task.tid, confirmed=False)
                users[idx].assigned = task.tid
                db.session.add(assignment)
                db.session.commit()
                idx += 1

            else:
                break
    else:
        for task, _ in tasks_with_distances:
            if idx < num_users:
                assignment = Assignment(uid=users[idx].uid, tid=task.tid, confirmed=False)
                users[idx].assigned = task.tid
                db.session.add(assignment)
                db.session.commit()
                idx += 1
            else:
                break

    return jsonify({'message': 'Assignment added'})


@tb.route('/test', methods=['GET'])
def test():
    # start=request.json.get('start')
    # end=request.json.get('end')

    message = BaiduDistance.short_distance2()
    return jsonify({'message': message}), 200
